package com.atguigu.myssm.myspringmvc;

import com.atguigu.myssm.ioc.BeanFactory;
import com.atguigu.qqzone.exceptions.DispatcherServletException;
import com.atguigu.utils.StringUtils;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;

/**
 * @ClassName: DispatcherServlet
 * @Description:
 * @Author: wty
 * @Date: 2022/12/7
 */
@WebServlet("*.do")
public class DispatcherServlet extends ViewBaseServlet {
    private BeanFactory beanFactory = null;

    public DispatcherServlet() {

    }

    /**
     * @param
     * @return void
     * @description Servlet初始化阶段，并且初始化BeanFactory对象
     * @date 2022/12/8 10:54
     * @author wty
     **/
    @Override
    public void init() throws ServletException {
        super.init();
        // 之前是在此处主动创建IOC容器
        // beanFactory = new ClassPathXmlApplicationContext();

        // 现在优化为从application作用域去获取
        Object objectBeanFactory = getServletContext().getAttribute("beanFactory");
        if (null != objectBeanFactory) {
            beanFactory = (BeanFactory) objectBeanFactory;
        } else {
            throw new DispatcherServletException("DispatcherServlet 出错了!");
        }

    }

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 设置编码
        // request.setCharacterEncoding("UTF-8");
        // 假设URL是:http://localhost:8080/pro15/hello.do
        // 那么servletPath 是hello.do

        String servletPath = request.getServletPath();
        /// hello.do
        System.out.println(servletPath);

        // 1.字符串截取 hello.do 得到 hello
        servletPath = servletPath.substring(1, servletPath.length() - 3);
        System.out.println(servletPath);

        // 2. hello 和 helloController对应上
        Object contorllerBeanObject = beanFactory.getBean(servletPath);


        // 下面的逻辑来自于FruitController
        String operate = request.getParameter("operate");
        if (StringUtils.isEmpty(operate)) {
            operate = "index";
        }

        try {
            Method declaredMethods[] = contorllerBeanObject.getClass().getDeclaredMethods();
            for (Method declaredMethod : declaredMethods) {
                if (operate.equals(declaredMethod.getName())) {
                    // 1.统一获取请求参数
                    // 获取当前方法的所有参数，返回参数数组
                    Parameter[] parameters = declaredMethod.getParameters();
                    // parametersobjectsValue用来存放参数的值
                    Object[] parametersobjectsValue = new Object[parameters.length];
                    for (int i = 0; i < parameters.length; i++) {
                        Parameter parameter = parameters[i];
                        String parameterName = parameter.getName();

                        // 如果参数名是request、response、session那么单独处理
                        if ("request".equals(parameterName)) {
                            parametersobjectsValue[i] = request;
                        } else if ("response".equals(parameterName)) {
                            parametersobjectsValue[i] = response;
                        } else if ("session".equals(parameterName)) {
                            parametersobjectsValue[i] = request.getSession();
                        } else {
                            // 从请求中获取参数值
                            String parameterValue = request.getParameter(parameterName);

                            //当前页面http://localhost:8080/pro16/fruit.do?pageNumber=2
                            // 最后的2在parameterValue中是"2"会报错argument type mismatch
                            String typeName = parameter.getType().getName();
                            if ("java.lang.String".equals(typeName)) {
                                parametersobjectsValue[i] = parameterValue;
                            } else if (null != parameterValue && "java.lang.Integer".equals(typeName)) {
                                parametersobjectsValue[i] = Integer.parseInt(parameterValue);
                            } else {
                                parametersobjectsValue[i] = parameterValue;
                            }
                        }
                    }
                    // 2.controller组件中的方法调用
                    declaredMethod.setAccessible(true);
                    Object o = declaredMethod.invoke(contorllerBeanObject, parametersobjectsValue);

                    // 3.视图处理:
                    String methodReturnStr = (String) o;
                    if (methodReturnStr.startsWith("redirect")) {
                        // 比如 redirect:fruit.do
                        // 截取后只想要 fruit.do
                        String redirectStr = methodReturnStr.substring("redirect:".length());
                        response.sendRedirect(redirectStr);
                    } else {
                        // 比如 edit
                        super.processTemplate(methodReturnStr, request, response);
                    }
                } else {
                    //throw new RuntimeException("operate值非法!");
                }
            }
        } catch (IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
            throw new DispatcherServletException("DispatcherServlet 出错了!");
        }
    }
}
// 常间错误 argument type mismatch
// 当前页面http://localhost:8080/pro16/fruit.do?pageNumber=2